package com.apexsoft.monitor.common.http;

import com.alibaba.fastjson.JSONObject;
import com.apexsoft.front.common.support.Result;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.Map.Entry;


public class HttpHelper {
	private static final Logger log = LogManager.getRootLogger();

	public static Object post(String url, Map<String, String> params, ResponseHandler<?> handler) throws ServerErrorException {

		RequestBuilder rb = RequestBuilder.post();
		for (Entry<String, String> e : params.entrySet()) {
			rb.addParameter(e.getKey(), e.getValue());
		}
		rb.setUri(url);
		CloseableHttpClient client = null;
		try {
			client = HttpClients.createMinimal();
			return client.execute(rb.build(), handler);
		} catch (ClientProtocolException e) {
			throw new ServerErrorException("服务器[" + url + "]连接不通", e);
		} catch (IOException e) {
			throw new ServerErrorException("服务器[" + url + "]访问异常", e);
		} finally {
			if (client != null) {
				try {
					client.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
		}
	}

	public static Object post(String url, Map<String, String> params, Map<String, File> fileParams, ResponseHandler<?> handler) throws ServerErrorException {

		MultipartEntityBuilder meb = MultipartEntityBuilder.create();
		meb.setCharset(Charset.forName("UTF-8"));
		meb.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
		if (params != null) {
			for (Entry<String, String> e : params.entrySet()) {
				meb.addTextBody(e.getKey(), e.getValue(), ContentType.create("text/plain", "UTF-8"));
			}
		}
		if (fileParams != null) {
			for (Entry<String, File> e : fileParams.entrySet()) {
				meb.addBinaryBody(e.getKey(), e.getValue());
			}
		}

		HttpPost hp = new HttpPost(url);
		HttpEntity entity = meb.build();
		hp.setEntity(entity);

		CloseableHttpClient client = null;
		try {
			client = HttpClients.createMinimal();
			return client.execute(hp);
		} catch (ClientProtocolException e) {
			throw new ServerErrorException("服务器[" + url + "]连接不通", e);
		} catch (IOException e) {
			throw new ServerErrorException("服务器[" + url + "]访问异常", e);
		} finally {
			if(client!=null){
				try {
					client.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
		}
	}

	public static Object post(String url, String paramsJson,Map hearderMap)throws ServerErrorException {
		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		JSONObject returnObj = new JSONObject();
		String returnValue = "{code:-1}";
		try{
			httpclient = HttpClients.custom().build();

			HttpPost httpPost = new HttpPost(url);
			httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");

			StringEntity requestEntity = new StringEntity(paramsJson,"UTF-8");

			httpPost.setEntity(requestEntity);
			if(hearderMap!=null && hearderMap.size()>0){
				Set<String> keys = hearderMap.keySet();
				for(String key:keys){
					httpPost.setHeader(key,(String)(hearderMap.get(key)));
				}
			}
			response = httpclient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if(statusCode==HttpStatus.SC_OK){
				HttpEntity entity = response.getEntity();
				returnValue = EntityUtils.toString(entity);
			}else{
				returnObj.put(Result.CODE,Result.EC_1000);
				returnObj.put(Result.NOTE,"请求错误代码：【"+statusCode+"】");
				returnValue = returnObj.toJSONString();
			}
		}catch (Exception e) {
			returnObj.put(Result.CODE,Result.EC_1000);
			returnObj.put(Result.NOTE,e.getMessage());
			returnValue = returnObj.toJSONString();
			log.error(e.getMessage(), e);
			//throw new ServerErrorException("服务器[" + url + "]连接不通", e);
		} finally {
			try{
				if(httpclient!=null){
					httpclient.close();
				}
				if(response!=null){
					response.close();
				}
			}catch(Exception e){
				log.error(e.getMessage(), e);
			}
		}
		return returnValue;
	}

	public static void post(String url, Map<String, String> params, Map<String, MultipartFile> fileParams,HttpServletResponse response) throws IOException {
		MultipartEntityBuilder meb = MultipartEntityBuilder.create();
		meb.setCharset(Charset.forName("UTF-8"));
		meb.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
		if (params != null) {
			for (Entry<String, String> e : params.entrySet()) {
				meb.addTextBody(e.getKey(), e.getValue(), ContentType.create("text/plain", "UTF-8"));
			}
		}
		if (fileParams != null) {
			for (Entry<String, MultipartFile> e : fileParams.entrySet()) {
				meb.addBinaryBody(e.getKey(), e.getValue().getInputStream(), ContentType.create(e.getValue().getContentType(), "UTF-8"), e.getValue().getOriginalFilename());
			}
		}
		HttpPost hp = new HttpPost(url);
		hp.addHeader("sys-flag","ifs");
		HttpEntity  entity = meb.build();
		hp.setEntity(entity);
		CloseableHttpClient httpclient = null;
        OutputStream os = null;
		InputStream is = null;
		try {
			if(!url.startsWith("https")){
				httpclient = HttpClients.custom().build();  
			}else{
				httpclient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).build();  
			}
			HttpResponse hr  =  httpclient.execute(hp);
            if (hr == null) {
				response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
				return;
			}
			Header[] headers = hr.getAllHeaders();
			for (Header header : headers) {
				response.setHeader(header.getName(), header.getValue());
			}
			Integer statusCode = hr.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				response.setStatus(statusCode);
				return;
			}
			HttpEntity hrentity = hr.getEntity();
			is = hrentity.getContent();
			os = response.getOutputStream();
			hrentity.writeTo(os);
			os.flush();
		} catch (ClientProtocolException e) {
			throw new ServerErrorException("服务器[" + url + "]连接不通", e);
		} catch (IOException e) {
			throw new ServerErrorException("服务器[" + url + "]访问异常", e);
		} finally {
			if(httpclient!=null){
				try {
					httpclient.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
            if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
		}
	}
	 /** 
     * 创建SSL安全连接 
     * 
     * @return 
     */  
    private static SSLConnectionSocketFactory createSSLConnSocketFactory() {  
        SSLConnectionSocketFactory sslsf = null;  
        try {  
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {  
  
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
                    return true;  
                }  
            }).build();  
            sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {  
  
                @Override  
                public boolean verify(String arg0, SSLSession arg1) {  
                    return true;  
                }  
  
                @Override  
                public void verify(String host, SSLSocket ssl) throws IOException {  
                }  
  
                @Override  
                public void verify(String host, X509Certificate cert) throws SSLException {  
                }  
  
                @Override  
                public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {  
                }  
            });  
        } catch (GeneralSecurityException e) {  
            e.printStackTrace();  
        }  
        return sslsf;  
    }  
	public static void post(String url, Map<String, String> params, HttpServletResponse response) throws ServerErrorException {
		HttpPost httpost = new HttpPost(url);
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		httpost.addHeader("sys-flag","ifs");
		Set<String> keySet = params.keySet();
		for (String key : keySet) {
			nvps.add(new BasicNameValuePair(key, params.get(key)));
		}
		try {
			httpost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
		} catch (UnsupportedEncodingException e) {
			log.warn(e.getMessage(), e);
		}
		CloseableHttpClient httpclient = null;
		OutputStream os = null;
		InputStream is = null;
		try {
			if(!url.startsWith("https")){
				httpclient = HttpClients.custom().build();  
			}else{
				httpclient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).build();  
			}

			HttpResponse hr = httpclient.execute(httpost);
			if (hr == null) {
				response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
				return;
			}
			Header[] headers = hr.getAllHeaders();
			for (Header header : headers) {
				response.setHeader(header.getName(), header.getValue());
			}
			Integer statusCode = hr.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				response.setStatus(statusCode);
				return;
			}
			HttpEntity entity = hr.getEntity();
			is = entity.getContent();
			os = response.getOutputStream();
			entity.writeTo(os);
			os.flush();
		} catch (ClientProtocolException e) {
			throw new ServerErrorException("服务器[" + url + "]连接不通", e);
		} catch (IOException e) {
			throw new ServerErrorException("服务器[" + url + "]访问异常", e);
		} catch (Exception e) {
			log.error(e);
			response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
			if (httpclient != null) {
				try {
					httpclient.close();
				} catch (IOException e) {
					log.warn(e.getMessage(), e);
				}
			}
		}
	}



    public static String sendPostRequestByParam(String url, Map<String,String>  params)
            throws Exception {
        HttpPost httpost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        httpost.addHeader("sys-flag","ifs");
        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            nvps.add(new BasicNameValuePair(key, params.get(key)));
        }
        try {
            httpost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            log.warn(e.getMessage(), e);
        }
        CloseableHttpClient httpclient = null;

        try {
            if(!url.startsWith("https")){
                httpclient = HttpClients.custom().build();
            }else{
                httpclient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).build();
            }

            HttpResponse hr = httpclient.execute(httpost);

            HttpEntity entity = hr.getEntity();
            if (entity != null) {
                String  responseContent = EntityUtils.toString(entity, "UTF-8");
                return responseContent;
            }
        } catch (ClientProtocolException e) {
            throw new ServerErrorException("服务器[" + url + "]连接不通", e);
        } catch (IOException e) {
            throw new ServerErrorException("服务器[" + url + "]访问异常", e);
        } catch (Exception e) {
            log.error(e);
        } finally {

            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                    log.warn(e.getMessage(), e);
                }
            }
        }
        return "";
    }

    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        byte[] data = outStream.toByteArray();
        outStream.close();
        inStream.close();
        return data;
    }

    public static void main(String[] args) throws ServerErrorException, FileNotFoundException {
        String fullUrl ="http://127.0.0.1:9080/resource/uploadJar";
        Map<String, File> inputStreamMap = new HashMap<>();

        inputStreamMap.put("Filedata", new File("D:\\soft\\jsoup-1.7.2.jar"));
        Map<String, String> params = new HashMap<>();
        params.put("desc", "desc");
        params.put("filename", "hello");
//            multipartFileMap.
        HttpHelper.post(fullUrl, params,inputStreamMap, null);
    }
}
